#include "msgsocket.h"
#include "command.h"
#include "config.h"
#include "databasemagr.h"

#include <QFile>
#include <QTime>
#include <QDebug>
#include <QHostAddress>
#include <QDataStream>
#include <QApplication>

MsgSocket::MsgSocket(QObject *parent) :
    QObject(parent)
{
    m_socket = new QTcpSocket(this);
}

MsgSocket::~MsgSocket()
{
    SltSendOffline();
}

void MsgSocket::CheckConnected()
{
    if (m_socket->state() != QTcpSocket::ConnectedState)
    {
        m_socket->connectToHost(Config::m_strHostAddr, Config::m_nMsgPort);
    }
}

/**
 * @brief MsgSocket::ColseConnected
 * 主动断开连接
 */
void MsgSocket::closeConnected()
{
    if (m_socket->isOpen())
    {
        m_socket->abort();
    }
}

/**
 * @brief MsgSocket::ConnectToHost
 * 链接服务器接口
 * @param host
 * @param port
 */
void MsgSocket::ConnectToHost(const QString &host, const int &port)
{
    connect(m_socket, SIGNAL(readyRead()),
            this, SLOT(SltReadyRead()));
    connect(m_socket, SIGNAL(connected()),
            this, SLOT(SltConnected()));
    connect(m_socket, SIGNAL(disconnected()),
            this, SLOT(SltDisconnected()));
    if(m_socket->isOpen())
    {
        m_socket->abort();
    }
    m_socket->connectToHost(host, port);
}

/**
 * @brief MsgSocket::ConnectToHost
 * 链接服务器接口
 * @param host
 * @param port
 */
void MsgSocket::ConnectToHost(const QHostAddress &host, const int &port)
{
    if (m_socket->isOpen()) m_socket->abort();
    m_socket->connectToHost(host, port);
}

/**
 * @brief MsgSocket::SltSendMessage
 * tcp socket消息管理
 * @param type
 * @param dataVal
 */
void MsgSocket::SltSendMessage(const quint8 &type, const QJsonValue &dataVal)
{
    // 构建 Json 对象
    QJsonObject json;
    json.insert("type", type);
    json.insert("from", m_localUser.m_id);
    json.insert("data", dataVal);

    // 构建 Json 文档
    QJsonDocument document;
    document.setObject(json);
    Config::m_packetSendNumber++;
    Config::m_rateSendByte += document.toJson().length();
    QTime *t = new QTime;
    t->start();
//    Config::m_msgTimeMap.insert(index, t);
    m_socket->write(document.toJson(QJsonDocument::Compact));
}

/**
 * @brief MsgSocket::SltSendOnline
 * 发送上线消息
 */
void MsgSocket::SltSendOnline()
{
    // 上线的时候给当前好友上报下状态
    QJsonArray friendArr = DataBaseMagr::Instance()->GetMyFriend(m_localUser.m_id);
    // 组织Jsonarror
    SltSendMessage(UserOnLine, friendArr);
}

/**
 * @brief MsgSocket::SltDisconnected
 */
void MsgSocket::SltDisconnected()
{
    qDebug() << "has disconnecetd";
    m_socket->abort();
    emit signalStatus(DisConnectedHost);
}

/**
 * @brief MsgSocket::SltConnected
 */
void MsgSocket::SltConnected()
{
    qDebug() << "has connecetd";
    emit signalStatus(ConnectedHost);
}


/**
 * @brief MsgSocket::SltReadyRead
 * 服务器消息处理
 */
void MsgSocket::SltReadyRead()
{
    // 读取socket数据
    QByteArray byRead = m_socket->readAll();
    Config::m_packetRecvNumber++;
    Config::m_rateRecvByte += byRead.length();

    QJsonParseError jsonError;
    // 转化为 JSON 文档
    QJsonDocument doucment = QJsonDocument::fromJson(byRead, &jsonError);

    // 解析未发生错误
    if (!doucment.isNull() && (jsonError.error == QJsonParseError::NoError))
    {
        // JSON 文档为对象
        if (doucment.isObject()) {
            // 转化为对象
            QJsonObject jsonObj = doucment.object();
            QJsonValue dataVal = jsonObj.value("data");

            int nType = jsonObj.value("type").toInt();

            // 根据消息类型解析服务器消息
            switch (nType) {
            case Register: ParseReister(dataVal); break;
            case Login: ParseLogin(dataVal); break;
            case UserOnLine: emit signalMessage(UserOnLine, dataVal);break;
            case UserOffLine: emit signalMessage(UserOffLine, dataVal); break;
            case Logout: m_socket->abort(); break;
            case UpdateHeadPic: emit signalMessage(UpdateHeadPic, dataVal); break;
            case AddFriend: emit signalMessage(AddFriend, dataVal); break;
            case AddGroup: emit signalMessage(AddGroup, dataVal); break;
            case AddFriendRequist: emit signalMessage(AddFriendRequist, dataVal); break;
            case AddGroupRequist: emit signalMessage(AddGroupRequist, dataVal); break;
            case CreateGroup: emit signalMessage(CreateGroup, dataVal); break;
            case GetMyFriends: emit signalMessage(GetMyFriends, dataVal); break;
            case GetMyGroups: emit signalMessage(GetMyGroups, dataVal); break;
            case RefreshFriends: emit signalMessage(RefreshFriends, dataVal); break;
            case RefreshGroups: emit signalMessage(RefreshGroups, dataVal); break;
            case SendMsg: emit signalMessage(SendMsg, dataVal); break;
            case SendGroupMsg: emit signalMessage(SendGroupMsg, dataVal); break;
            case SendFile: emit signalMessage(SendFile, dataVal); break;
            case SendPicture: emit signalMessage(SendPicture, dataVal); break;
            default:
                break;
            }
        }
    }
}

/**
 * @brief MsgSocket::ParseLogin
 * 解析登录信息
 * @param reply
 */
void MsgSocket::ParseLogin(const QJsonValue &dataVal)
{
    // data 的 value 是对象
    if(dataVal.isObject())
    {
        QJsonObject dataObj = dataVal.toObject();
        int code = dataObj.value("code").toInt();
        QString msg = dataObj.value("msg").toString();
        m_localUser.m_head = dataObj.value("head").toString();

        if (0 == code && msg == "ok")
        {
            m_localUser.m_id = dataObj.value("id").toInt();

            emit signalStatus(LoginSuccess);
        }else if (-1 == code){
            emit signalStatus(LoginPasswdError);
        }else if (-2 == code) {
            emit signalStatus(LoginRepeat);
        }
    }
}

/**
 * @brief MsgSocket::ParseReister
 * 解析注册信息
 * @param reply
 */
void MsgSocket::ParseReister(const QJsonValue &dataVal)
{
    // data 的 value 是对象
    if(dataVal.isObject())
    {
        QJsonObject dataObj = dataVal.toObject();
        m_localUser.m_id = dataObj.value("id").toInt();

        if(-1 != m_localUser.m_id)
        {
            emit signalStatus(RegisterOk);
        }else 
        {
            emit signalStatus(RegisterFailed);
        }
    }
}

/**
 * @brief MsgSocket::SendOffline
 */
void MsgSocket::SltSendOffline()
{
    QJsonObject json;
    json.insert("id", m_localUser.m_id);
    QJsonArray friendArr = DataBaseMagr::Instance()->GetMyFriend(m_localUser.m_id);
    json.insert("friends", friendArr);

    // 通知我的好友，我下线了
    this->SltSendMessage(Logout, json);
}

